﻿using System.Diagnostics;
using System.IO;
using System.Text;

namespace NH3SQLLogger
{
    public class CallingMethod
    {
        public static string GetCallingMethodInfo()
        {
            var stackTrace = new StackTrace(true);
            var frameCount = stackTrace.FrameCount;

            var info = new StringBuilder();
            var prefix = "-- ";
            for (var i = frameCount - 1; i >= 0; i--)
            {
                var sf = stackTrace.GetFrame(i);
                var stackFrameInfo = getStackFrameInfo(sf, onlyIncludeInfoWithFileLine: true);
                if (string.IsNullOrWhiteSpace(stackFrameInfo))
                    continue;

                info.AppendLine(prefix + stackFrameInfo);
                prefix = "-" + prefix;
            }

            return info.ToString();
        }

        private static string getStackFrameInfo(StackFrame stackFrame, bool onlyIncludeInfoWithFileLine = false)
        {
            if (stackFrame == null) return string.Empty;

            var method = stackFrame.GetMethod();
            if (method == null) return string.Empty;

            //we don't need the current asm's info.
            if (method.ReflectedType == typeof(CallingMethod) || method.ReflectedType == typeof(EventsLogger))
                return string.Empty;

            var methodString = method.ToString();

            var returnName = string.Empty;
            var methodSignature = methodString;

            var splitIndex = methodString.IndexOf(' ');
            if (splitIndex > 0)
            {
                returnName = methodString.Substring(0, splitIndex);
                methodSignature = methodString.Substring(splitIndex + 1, methodString.Length - splitIndex - 1);
            }

            var type = method.ReflectedType;
            var typeNameFull = type.FullName;
            var lineNumber = stackFrame.GetFileLineNumber();

            var fileLine = string.Empty;
            var filePath = stackFrame.GetFileName();
            if (!string.IsNullOrEmpty(filePath))
            {
                var fileName = Path.GetFileName(filePath);
                fileLine = string.Format("File={0}, Line={1}", fileName, lineNumber);
            }

            //there is no valid .pdb file
            if (!File.Exists(filePath) && onlyIncludeInfoWithFileLine)
                return string.Empty;
            //couldn't extract the source file name
            if (string.IsNullOrWhiteSpace(fileLine) && onlyIncludeInfoWithFileLine)
                return string.Empty;

            var methodSignatureFull = string.Format("{0} {1}.{2}", returnName, typeNameFull, methodSignature);
            return string.Format("{0} [{1}]", methodSignatureFull, fileLine);
        }
    }
}
